package com.chart.web.controller.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chart.chart.domian.req.UListReq;
import com.chart.chart.domian.resp.UserResp;
import com.chart.chart.manager.UserStatisticsManager;
import com.chart.common.annotation.Log;
import com.chart.common.core.controller.BaseController;
import com.chart.common.core.domain.AjaxResult;
import com.chart.common.core.domain.entity.SysDept;
import com.chart.common.core.domain.entity.SysRole;
import com.chart.common.core.domain.entity.SysUser;
import com.chart.common.core.domain.entity.UserCoinLog;
import com.chart.common.core.page.TableDataInfo;
import com.chart.common.enums.BusinessType;
import com.chart.common.utils.SecurityUtils;
import com.chart.common.utils.StringUtils;
import com.chart.common.utils.poi.ExcelUtil;
import com.chart.system.domain.SysUserRole;
import com.chart.system.service.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.ibatis.annotations.Delete;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author chart
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysPostService postService;
    @Autowired
    private IUserCoinLogsService userCoinLogsService;


    @Autowired SysUserRoleService sysUserRoleService;

    @Resource
    private UserStatisticsManager userManager;


 //   @Value("${wechat.token}")
//    @Value("${wxpay.token}")
//    private String TOKEN;

    /**
     * 获取用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user) {
        IPage<SysUser> list = userService.selectUserList(startPage(), user);
        return getDataTable(list);
    }

    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysUser user) {
        List<SysUser> list = userService.selectUserList(startPage(), user).getRecords();
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, list, "用户数据");
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return success(message);
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }

    /**
     * 根据用户编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = {"/", "/{userId}"})
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        userService.checkUserDataScope(userId);
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId)) {
            SysUser sysUser = userService.selectUserById(userId);
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
        }
        return ajax;
    }

    /**
     * 新增用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        if (!userService.checkUserNameUnique(user)) {
            return error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        if (!userService.checkUserNameUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUser(user));
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds) {
        if (ArrayUtils.contains(userIds, getUserId())) {
            return error("当前用户不能删除");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 根据用户编号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId) {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }

    /**
     * 用户授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds) {
        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return success();
    }

    /**
     * 获取部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept) {
        return success(deptService.selectDeptTreeList(dept));
    }


    /**
     * 完善用户信息
     */
    @PostMapping("/edit")
    public AjaxResult edit1(@Validated @RequestBody SysUser user) {

        String otherKnowChannel = user.getOtherKnowChannel();
        Integer knowChannel = user.getKnowChannel();
        //如果id==16 取值 otherPost
        Long userId = SecurityUtils.getUserId();
        if (!SecurityUtils.isAdmin(userId)) {
            user.setFreeOper(3);
            user.setUserId(userId);
            Boolean result = userService.editUser(user);
            if (result) {
                SysUser sysUser = new SysUser();
                sysUser.setUserId(userId);
                sysUser.setHasComplete(1);
                sysUser.setKnowChannel(knowChannel);
                sysUser.setOtherKnowChannel(otherKnowChannel);
                userService.updateById(sysUser);
                return AjaxResult.success();
            }
        }
        return AjaxResult.success();
    }


    /**
     * 修改用户信息
     */
    @GetMapping("/updateUser")
    public AjaxResult update(Integer hasLoggedIn) {
        //如果id==16 取值 otherPost
        Long userId = SecurityUtils.getUserId();

        SysUser sysUser1 = userService.queryById(userId);
        Integer hasLoggedIn1 = sysUser1.getHasLoggedIn();
        Integer hasComplete = sysUser1.getHasComplete();
        if (hasLoggedIn1 == 0) {
            //添加5个席位
            UserCoinLog userCoinLog = new UserCoinLog();
            userCoinLog.setUserId(userId);
            userCoinLog.setSeatCount(5);
            userCoinLog.setBehavior("SEATCOUNT");
            userCoinLogsService.save(userCoinLog);
        }

        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setHasLoggedIn(hasLoggedIn);
        userService.updateById(sysUser);

//        UserCoinLog userCoinLog = new UserCoinLog();
//        userCoinLog.setUserId(userId);
//        userCoinLog.setSeatCount(5);
//        userCoinLogsService.save(userCoinLog);


        return AjaxResult.success();
    }


    /**
     * 统计当前面用户总数
     *
     * @return
     */
    @GetMapping("/getTotalUserCount")
    public AjaxResult getTotalUserCount() {
        Long total = userService.getTotalUserCount();
        return AjaxResult.success(total);
    }

    /**
     * 获取每日新注册用户数
     */
    @GetMapping("/queryDailyNewUserCount")
    public AjaxResult getDailyNewUserCount() {
        Long total = userService.getDailyNewUserCount();
        return AjaxResult.success(total);
    }


    /**
     * 每日登录用户数（DAU）\(MAU)
     * 根据用户表
     */
    @GetMapping("/queryDailyAndMonthlyActiveUsers")
    public AjaxResult queryDailyAndMonthlyActiveUsers() {
        Long totalDau = userService.getDailyActiveUserCount();
        Long totalMau = userService.getMonthlyActiveUserCount();
        HashMap<String, Long> totalCount = new HashMap<>();
        totalCount.put("totalDau", totalDau);
        totalCount.put("totalMau", totalMau);
        return AjaxResult.success(totalCount);
    }


    /**
     * 每日登录用户数（DAU）\(MAU)
     * 根据记录表
     */
    @GetMapping("/queryDailyAndMonthlyActiveUserCoinLog")
    public AjaxResult queryDailyAndMonthlyActiveUserCoinLog() {


        //昨日登录用户数
        LocalDateTime startOfYesterday = LocalDate.now().minusDays(1).atStartOfDay();
        LocalDateTime endOfYesterday = LocalDate.now().minusDays(1).atTime(23, 59, 59, 999999999);
        LambdaQueryWrapper<UserCoinLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCoinLog::getAction, "LOGINLOG");
        wrapper.le(UserCoinLog::getCreateTime, endOfYesterday); // 小于等于昨天的结束时间
        wrapper.ge(UserCoinLog::getCreateTime, startOfYesterday); // 大于等于昨天的开始时间
          // 查询昨天的登录记录
        List<UserCoinLog> listYesterday = userCoinLogsService.list(wrapper);
        int yesterdayLoginSize = listYesterday.size();


        //今日登录用户数
        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
        LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59, 999999999);
        LambdaQueryWrapper<UserCoinLog> lqw = new LambdaQueryWrapper<>();
        lqw.eq(UserCoinLog::getAction, "LOGINLOG");
        lqw.le(UserCoinLog::getCreateTime, endOfDay);//小于等于
        lqw.ge(UserCoinLog::getCreateTime, startOfDay); //大于等于
        List<UserCoinLog> listDay = userCoinLogsService.list(lqw);
        int dayLogSize = listDay.size();


        // 本月登录用户数
        LocalDate today = LocalDate.now();
        LocalDate startOfMonth = today.withDayOfMonth(1);
        LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());
        LocalDateTime startOfMonthDateTime = startOfMonth.atStartOfDay();
        LocalDateTime endOfMonthDateTime = lastDayOfMonth.atTime(23, 59, 59, 999999999);
        LambdaQueryWrapper<UserCoinLog> monthlyWrapper = new LambdaQueryWrapper<>();
        monthlyWrapper.eq(UserCoinLog::getAction, "LOGINLOG");
        monthlyWrapper.ge(UserCoinLog::getCreateTime, startOfMonthDateTime);
        monthlyWrapper.le(UserCoinLog::getCreateTime, endOfMonthDateTime);
        List<UserCoinLog> listMonth = userCoinLogsService.list(monthlyWrapper);
        int monthLogSize = listMonth.size();

        //总用户数
        Long totalUserNumberLong = userService.getTotalUserCount();
        int totalUserNumber = totalUserNumberLong.intValue();


        UListReq req = new UListReq();
        req.setStartTime("");
        req.setEndTime("");

       // List<UserResp> list = userManager.getListBy(req);
        Integer  registerTotal =  userService.selectCount();

        //昨日新注册用户数
        LambdaQueryWrapper<SysUser> Wrapper = new LambdaQueryWrapper<>();
        Wrapper.le(SysUser::getCreateTime, endOfYesterday);
        Wrapper.ge(SysUser::getCreateTime, startOfYesterday);
        int  registeredYesterday = userService.list(Wrapper).size();
        HashMap<String, Integer> totalCount = new HashMap<>();
        totalCount.put("yesterdayLoginSize", yesterdayLoginSize);
        totalCount.put("dayLogSize", dayLogSize);
        totalCount.put("monthLogSize", monthLogSize);
        totalCount.put("totalUserNumber", registerTotal);
        totalCount.put("registeredYesterday", registeredYesterday);
        return AjaxResult.success(totalCount);
    }


    /**
     * 删除用户
     * @param userId
     * @return
     */

    @GetMapping("/delUser")
    public  AjaxResult delUser(String userId) {
        if (userId == null) {
            return AjaxResult.error("用户ID不能为空");
        }
        long userIdAsLong = Long.parseLong(userId);
        userService.deleteUserById(userIdAsLong);
        userService.deleteUser(userIdAsLong);
        return AjaxResult.success();
    }








    // 为用户生成二维码
//    @PostMapping("/generate")
//    @GetMapping("system/user/generate")
//    public HashMap<Object, Object> generateQrcode(@RequestParam String phoneNum) {
//        HashMap<Object, Object> map = null;
//        try {
//            map = userService.generateUserQrcode(phoneNum);
//        } catch (JsonProcessingException e) {
//            throw new RuntimeException(e);
//        }
//        return map;
//
//    }


    private static final String TOKEN = "X4yZ7k9B3mVfD1nQ5tG8wL2pR78";  // 与微信公众号后台配置的 Token 保持一致



    // 微信公众平台的 GET 请求，用于验证 token
    @GetMapping("/event")
    public void verifyToken(@RequestParam String signature,
                            @RequestParam String timestamp,
                            @RequestParam String nonce,
                            @RequestParam String echostr,
                            HttpServletResponse response) {
        System.out.println("微信官方回调了我的这个接口");
        try {
            // 1. 将 token, timestamp, nonce 按字典序排序
            String[] arr = {TOKEN, timestamp, nonce};
            Arrays.sort(arr);

            // 2. 将三个参数拼接成字符串并进行 SHA1 加密
            StringBuilder content = new StringBuilder();
            for (String s : arr) {
                content.append(s);
            }
            String tempSignature = DigestUtils.sha1Hex(content.toString());

            // 3. 校验签名是否来自微信
            if (tempSignature.equals(signature)) {
                response.getWriter().write(echostr);  // 验证成功，返回 echostr
            } else {
                response.getWriter().write("fail");  // 验证失败
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 微信公众平台的 POST 请求，接收事件推送
    @PostMapping("/event")
    public void handleWechatEvents(@RequestBody String xmlData, HttpServletResponse response) {
        try {
            System.out.println("微信官方回调了我的接口");
            // 解析微信推送的XML数据
            Document document = DocumentHelper.parseText(xmlData);
            Element root = document.getRootElement();
            // 获取消息类型和事件类型
            String msgType = root.elementText("MsgType");
            String event = root.elementText("Event");
            String openId = root.elementText("FromUserName");  // 提取用户的 OpenID

            // 处理事件推送
            if ("event".equals(msgType)) {
                if ("subscribe".equals(event)) {
                    // 处理用户首次关注公众号事件
                    String eventKey = root.elementText("EventKey");
                    if (eventKey != null && eventKey.startsWith("qrscene_")) {
                        // 提取场景值中的 userId
                        String userId = eventKey.replace("qrscene_", "");
                        System.out.println("用户通过二维码关注公众号，OpenID: " + openId + ", 用户ID: " + userId);
                        handleSubscribeEvent(openId, userId);

                        //根据userId 更新openId
                        // 使用 MyBatis 查询后四位匹配的用户
                        SysUser user = userService.queryByUserIdSuffix(userId);
                        if(user != null){
                            Long userIds = user.getUserId();
                            //根据userId 更新openId

                            boolean flag =   userService.updateByuserId(userIds,openId);
                            System.out.println("userId1"+userIds);
                        }


                    } else {
                        System.out.println("用户直接关注了公众号，OpenID: " + openId);
                        handleSubscribeEvent(openId, null);  // 如果没有场景值，userId 为 null
                    }

                } else if ("unsubscribe".equals(event)) {
                    // 处理用户取消关注事件
                    System.out.println("用户取消关注公众号，OpenID: " + openId);
                    handleUnsubscribeEvent(openId);

                } else if ("SCAN".equals(event)) {
                    // 处理已关注用户扫描二维码事件
                    String eventKey = root.elementText("EventKey");
                    System.out.println("已关注用户扫描二维码，OpenID: " + openId + ", 场景值: " + eventKey);
                    handleScanEvent(openId, eventKey);
                }
            }

            // 回复微信服务器，防止重试
            response.getWriter().write("success");

        } catch (Exception e) {
            e.printStackTrace();
            try {
                response.getWriter().write("fail");
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    // 处理首次关注事件（附带二维码参数）
    private void handleSubscribeEvent(String openId, String userId) {
        if (userId != null) {
            // 处理通过带参数二维码关注的用户
            System.out.println("欢迎通过二维码关注的用户，OpenID: " + openId + ", 用户ID: " + userId);



            // 在这里可以将 openId 和 userId 保存到数据库，或者发送欢迎消息
            saveUserInfo(openId, userId);
        } else {
            // 处理直接关注的用户
            System.out.println("欢迎直接关注的用户，OpenID: " + openId);
            saveUserInfo(openId, null);  // 如果没有场景值，可以不保存 userId
        }
        // 在这里可以发送欢迎消息
    }

    // 处理取消关注事件
    private void handleUnsubscribeEvent(String openId) {
        System.out.println("用户取消关注，OpenID: " + openId);
        // 在这里更新数据库，记录用户的取消关注行为
        updateUserStatus(openId, false);
    }

    // 处理已关注用户扫描二维码事件
    private void handleScanEvent(String openId, String eventKey) {
        String userId = extractUserIdFromEventKey(eventKey);  // 提取用户ID
        System.out.println("已关注用户扫描二维码，OpenID: " + openId + ", 场景值: " + eventKey);
        System.out.println("已关注用户，场景值中提取的用户ID: " + userId);

        // 根据场景值和用户ID执行相应的业务逻辑
        saveScanEventInfo(openId, userId);
    }

    // 提取 userId 方法
    private String extractUserIdFromEventKey(String eventKey) {
        if (eventKey != null && !eventKey.isEmpty()) {
            try {
                // 尝试提取 userId (假设 eventKey 是数字形式的用户ID)
                return eventKey.replace("qrscene_", "");
            } catch (Exception e) {
                System.out.println("提取 userId 时发生错误: " + e.getMessage());
            }
        }
        return "未知用户ID";
    }

    // 模拟保存用户信息到数据库
    private void saveUserInfo(String openId, String userId) {
        // 在这里执行将 openId 和 userId 保存到数据库的操作
        System.out.println("保存用户信息到数据库，OpenID: " + openId + ", 用户ID: " + userId);
    }

    // 模拟更新用户状态（取消关注）
    private void updateUserStatus(String openId, boolean isActive) {
        // 在这里执行更新数据库中用户状态的操作
        System.out.println("更新用户状态为 " + (isActive ? "活跃" : "取消关注") + "，OpenID: " + openId);
    }

    // 保存二维码扫描事件的信息
    private void saveScanEventInfo(String openId, String userId) {
        // 在这里执行保存已关注用户扫描二维码后的事件信息的操作
        System.out.println("保存二维码扫描事件信息，OpenID: " + openId + ", 用户ID: " + userId);
    }
















}
